
#include <utest.h>

#include <hello/net/tcp_server.h>


void tcp_server_test()
{
    try
    {
        hello::tcp_server _srv(
            4399,
            "127.0.0.1",
            [](const std::string& _msg)
            {
                return _msg + " [FROM SERVER]";
            },
            2,
            2,
            4
        );

        _srv.start();
    }
    catch (const std::exception& e)
    {
        println("EPOLL SERVER ERROR:", e.what());
        throw e;
    }
}

void socket_client_001()
{
    const char* host = "127.0.0.1";
    int port = 4399;

    // 1. create client socket
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd < 0)
    {
        println("create socker error:", strerror(errno));
        return;
    }

    // 2. define server address
    sockaddr_in saddr {};
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = inet_addr(host);
    saddr.sin_port = htons(port);

    // 3. connect to server
    if (connect(cfd, (sockaddr*)&saddr, sizeof(saddr)) < 0)
    {
        println("connect to server error:", strerror(errno));
        close(cfd);
        return;
    }

    // 4. write to server
    std::string str = "This is an item!";
    size_t len = str.size();
    std::string msg((char*)&len, sizeof(len));
    msg.append(str);
    println("begin write...");
    auto wcnt = write(cfd, msg.c_str(), msg.size());
    if (wcnt < 0)
    {
        println("write error:", strerror(errno));
        close(cfd);
        return;
    }

    // 5. read from server
    char read_buf[256];
    println("begin read...");
    auto rcnt = read(cfd, read_buf, 256);

    size_t _data_len = *((size_t*)read_buf);
    println("data len:", _data_len);
    std::string _out_msg(read_buf + sizeof(size_t), _data_len);

    println("data:", _out_msg);

    close(cfd);
}

TEST(server, c001, true)
{
    tcp_server_test();
}

TEST(t001, c001, false)
{
    std::thread srv_t(tcp_server_test);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::thread cli_t_1(socket_client_001);
    std::thread cli_t_2(socket_client_001);
    std::thread cli_t_3(socket_client_001);
    cli_t_1.join();
    cli_t_2.join();
    cli_t_3.join();
    srv_t.detach();
}
